//========================================================================
/**
 * Author   : cuisw <shaovie@gmail.com>
 * Date     : 2008-01-08 11:54
 */
//========================================================================

#ifndef _MESSAGEBLOCK_H_
#define _MESSAGEBLOCK_H_
#include "Pre.h"

#include <malloc.h>

/**
 * @class MessageBlock
 *
 * @brief Message payload.
 */
class MessageBlock
{
public:
    enum
    {
        /// = Data and proto
        // Undifferentiated data message
        MB_DATA     = 0x01,

        /// = Control messages
        // Restart transmission after stop
        MB_START    = 0x80,

        // Stop transmission immediately
        MB_STOP     = 0x81,

        // Fatal error used to set u.u_error
        MB_ERROR    = 0x82,

        /// = Message class masks
        // Normal priority message mask
        MB_NORMAL   = 0x00,

        // High priority control message mask
        MB_PRIORITY = 0x80,

        // User-defined message mask
        MB_USER     = 0x200,
        MB_USER1    = 0x201,
        MB_USER2    = 0x202
    };
public:
    MessageBlock (const size_t size, int type = MB_DATA);

    MessageBlock (const char *pdata, int type = MB_DATA);

    virtual ~MessageBlock ();

    // get message data pointer
    char *base (void);

    // get message data len
    size_t size (void);

    // Message length is (wr_ptr - rd_ptr).
    size_t length (void) const;

    // get messageblock type
    int data_type (void) const;

    // set messageblock type
    void data_type (int type);

    // pointer to the MessageBlock directly ahead in the MessageQueue.
    // get link to next mb,
    MessageBlock *next (void) const;

    // set link to next mb,
    void next (MessageBlock *mb);

    // pointer to the MessageBlock directly behind in the MessageQueue.
    // get link to prev mb,
    MessageBlock *prev (void) const;

    // set link to prev mb,
    void prev (MessageBlock *mb);

    // Get the read pointer.
    char *rd_ptr (void) const;

    // Set the read pointer ahead n bytes.
    void rd_ptr (size_t n);

    // Get the write pointer.
    char *wr_ptr (void) const;

    // Set the write pointer ahead  n bytes.  This is used to compute
    // the <length> of a message.
    void wr_ptr (size_t n);

    // release message data which is alloced by MessageBlock, If the 
    // MessageBlock is a link, the release all of them. 
    void release (void);

    // sets the read and write pointers to align with the base.
    void reset (void);

    // release the memory which is alloced by MessageBlock,
    void clean (void);
protected:
    // point to beginning of message payload.
    char *	    mb_base_;

    int         release_base_;

    size_t	    mb_size_;

    // Message type
    int         mb_type_;

    // Pointer to beginning of next read.
    size_t rd_ptr_;

    // Pointer to beginning of next write.
    size_t wr_ptr_;

    // Pointer to previous message in the list.
    MessageBlock *  prev_;

    // Pointer to next message in the list.
    MessageBlock *  next_;
private:
    // = Disallow these operations
    MessageBlock &operator = (const MessageBlock & );

    MessageBlock (const MessageBlock &);
};

#include "MessageBlock.inl"
#include "Post.h"
#endif

